/*
 * Copyright (c) 2008, Xiong Yingfei, the University of Tokyo
 * All rights reserved.
 */
package ac.jp.u_tokyo.SyncLib.language3;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.omg.CORBA.CustomMarshal;

import sun.security.action.GetLongAction;

import ac.jp.u_tokyo.SyncLib.CompilerParameters;
import ac.jp.u_tokyo.SyncLib.language.Const;
import ac.jp.u_tokyo.SyncLib.language.EvaluationFailedException;
import ac.jp.u_tokyo.SyncLib.language3.LanguageParser.CustomMsgException;

public class HigherSyncDecl
{
	Map<String, Const> generic_para_list = new HashMap<String, Const>();
	List<Var> var_list = new LinkedList<Var>();
	String _name;
	SyncConstruct _sync;
	int _line;
		
	public HigherSyncDecl(int line)
	{
		super();
		_line = line;
	}

	public void setSync(SyncConstruct s) {
		_sync = s;
	}
	
	public void setName(String name) {
		_name = name;
	}
	
	public void addGenericParameter(String name, Const defaultValue, int line) throws CustomMsgException {
		if (generic_para_list.containsKey(name))
			throw new LanguageParser.CustomMsgException(name + " has already been defined.", line, 0);
		generic_para_list.put(name, defaultValue);
	}
	
	public void addVar(Var var) throws CustomMsgException {
		if (var_list.contains(var.getName()))
			throw new LanguageParser.CustomMsgException(var.getName() + " has already been defined.", var.getLine(), 0);
		var_list.add(var);
	}
	
	public ac.jp.u_tokyo.SyncLib.language.SyncDecl getResult() throws EvaluationFailedException{
		if (CompilerParameters.UseSpecializedFindby)
			if (_name.equals("findBy") && generic_para_list.size() == 1 && generic_para_list.keySet().iterator().next().equals("attr")
					&& var_list.size() == 3) {
				return NativeSyncFactory.createFindBy(_line);
			}
		
		ac.jp.u_tokyo.SyncLib.language.SyncDecl result = new ac.jp.u_tokyo.SyncLib.language.SyncDecl(_name);
		for (Entry<String, Const> entry : generic_para_list.entrySet()) {
			if (entry.getValue() == null) {
				result.addNonDefaultPara(entry.getKey());
			}
			else
				result.addDefaultPara(entry.getKey(), entry.getValue());
		}
		
		result.setBody(_sync.getBody(var_list, generic_para_list.keySet()));
		
		return result;
	}

	public String getName()
	{
		return _name;
	}

}
